package com.leviassaf.firstandroidapp;

import com.facebook.FacebookException;
import com.facebook.widget.FriendPickerFragment;
import com.facebook.widget.PickerFragment;
import com.facebook.widget.PlacePickerFragment;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Looper;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;

public class PickerActivity extends FragmentActivity {
	//constant for a Uri that will be be used in the decision to launch the friend picker
	public static final Uri FRIEND_PICKER = Uri.parse("picker://friend");
	//constant for a Uri that will be be used in the decision to launch the place picker
	public static final Uri PLACE_PICKER = Uri.parse("picker://place");

	//To display the friend picker, use the FriendPickerFragment class that provides a fragment that you can host in an activity
	private FriendPickerFragment friendPickerFragment;

	private PlacePickerFragment placePickerFragment;
	//variable used to listen for location updates
	private LocationListener locationListener;

	//constants that you'll use to configure the place picker fragment.
	//You're going to search a 1000 meter radius, ask for at most 50 results and query for restaurants. 
	//You'll also trigger a place picker data reload when the user's location changes more than 50 meters
	private static final int SEARCH_RADIUS_METERS = 1000;
	private static final int SEARCH_RESULT_LIMIT = 50;
	private static final String INITIAL_SEARCH_TEXT = "restaurant";
	private static final int LOCATION_CHANGE_THRESHOLD = 50;

	//If your app can't get a location, define a default location
	private static final Location LOCATION_HERZLIYA = new Location("") {
		{
			setLatitude(20.9784);
			setLongitude(23.5476);
		}
	};

	//override the onCreate() method to set the content view based on the layout. 
	//You'll also add private helper methods that handle error conditions and activity cleanup
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.pickers);

		Bundle bundleArgs = getIntent().getExtras();
		FragmentManager fragmentManager = getSupportFragmentManager();
		Fragment fragmentToShow = null;
		Uri uriIntent = getIntent().getData();
		if (FRIEND_PICKER.equals(uriIntent)) {
			//set up the display for the friend picker item
			if (savedInstanceState == null) {
				friendPickerFragment = new FriendPickerFragment(bundleArgs);
			} else {
				friendPickerFragment = (FriendPickerFragment) fragmentManager.findFragmentById(R.id.frameLayoutPickerFragment);
			}
			//Set the listener to handle errors
			friendPickerFragment.setOnErrorListener(
				new PickerFragment.OnErrorListener() {
					@Override
					public void onError(PickerFragment<?> fragment, FacebookException error) {
						PickerActivity.this.onError(error);
					}
				}
			);
			//The picker fragment includes a done button. 
			//To handle the button's click event, you can call the setOnDoneButtonClickedListener() method on a picker fragment instance and 
			//pass in a PickerFragment.OnDoneButtonClickedListener object that overrides the onDoneButtonClicked() method to handle the click event
			friendPickerFragment.setOnDoneButtonClickedListener(
				new PickerFragment.OnDoneButtonClickedListener() {
					@Override
					public void onDoneButtonClicked(PickerFragment<?> fragment) {
						finishActivity();
					}
				}
			);
			fragmentToShow = friendPickerFragment;
		}
		//detect an incoming Uri that corresponds to a place picker item click. 
		//Instantiate a PlacePickerFragment then set up a listener to detect a place selection change and 
		//call the finishActivity() method to save the change and close the activity
		else if (PLACE_PICKER.equals(uriIntent)) {
			if (savedInstanceState == null) {
				//the PlacePickerFragment class displays a list of nearby places
				//You'll host this fragment in the PickerActivity class. This activity launches when the user clicks on a friend or place in the list. 
				//The PlacePickerFragment is used if the incoming intent data matches a pre-defined place picker Uri.
				placePickerFragment = new PlacePickerFragment(bundleArgs);
			} else {
				placePickerFragment = (PlacePickerFragment) fragmentManager.findFragmentById(R.id.frameLayoutPickerFragment);
			}
			//Before loading the data, 
			//you may register for selection change notifications by calling setOnSelectionChangedListener on a picker fragment instance and 
			//passing in a PickerFragment.OnSelectionChangedListener instance that implements the onSelectionChanged() method
			placePickerFragment.setOnSelectionChangedListener(
				new PickerFragment.OnSelectionChangedListener() {
					@Override
					public void onSelectionChanged(PickerFragment<?> fragment) {
						//call finish since you can only pick one place
						finishActivity();
					}
				}
			);
			placePickerFragment.setOnDoneButtonClickedListener(
				new PickerFragment.OnDoneButtonClickedListener() {

				@Override
				public void onDoneButtonClicked(
							PickerFragment<?> fragment) {
						finishActivity();
					}
				}
			);
			fragmentToShow = placePickerFragment;
		} else {
			//Nothing to do, finish
			setResult(RESULT_CANCELED);
			finish();
			return;
		}
		fragmentManager.beginTransaction().replace(R.id.frameLayoutPickerFragment, fragmentToShow).commit();
	}

	private void onError(Exception error) {
		onError(error.getLocalizedMessage(), false);
	}

	private void onError(String errorMessage, final boolean finishActivity) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(R.string.error_dialog_title)
				.setMessage(errorMessage)
				.setPositiveButton(R.string.error_dialog_button_text,
						new DialogInterface.OnClickListener() {

							@Override
							public void onClick(DialogInterface dialog,
									int which) {
								if (finishActivity) {
									finishActivity();
								}
							}

						});
		builder.show();
	}

	//get the selected friends by calling the getSelection() method on a FriendPickerFragment instance
	//The selected friends will be of type List<GraphUser>, which is a list of GraphUser objects that represent strongly-typed Facebook users
	private void finishActivity() {
		ScrumptiousApplication app = (ScrumptiousApplication) getApplication();
		if (FRIEND_PICKER.equals(getIntent().getData())) {
			if (friendPickerFragment != null) {
				//save the friend selection
				app.setSelectedUsers(friendPickerFragment.getSelection());
			}
		}
		else if (PLACE_PICKER.equals(getIntent().getData())){
			if (placePickerFragment != null){
				//save the selected place
				app.setSelectedPlace(placePickerFragment.getSelection());
			}
		}
		setResult(RESULT_OK, null);
		finish();
	}

	//Now that the view's ready, initiate the data load when the activity becomes visible by 
	//overriding the onStart() method
	@Override
	protected void onStart() {
		super.onStart();
		if (FRIEND_PICKER.equals(getIntent().getData())) {
			//call the loadData() method of the FriendPickerFragment instance
			try {
				friendPickerFragment.loadData(false);
			} catch (Exception ex) {
				onError(ex);
			}
		} else {
			//load the place picker data
			if (PLACE_PICKER.equals(getIntent().getData())) {
				try {
					//get a LocationManager service and if there is an enabled provider, 
					//you'll save the last known location, then register a listener for location updates.
					Location location = null;
					//Instantiate the default criteria for a location provider
					Criteria criteria = new Criteria();
					//Get a location manager from the system services
					LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
					//Get the location provider that best matches the criteria
					String strBestProvider = locationManager.getBestProvider(criteria, false);
					if (strBestProvider != null) {
						//Get the user's last known location
						location = locationManager.getLastKnownLocation(strBestProvider);
						if (locationManager.isProviderEnabled(strBestProvider) && locationListener == null) {
							//Set up a location listener if one is not already set up and the selected provider is enabled
							locationListener = new LocationListener() {
								//The location update listener will trigger a place picker reload when the location changes beyond a certain threshold
								@Override
								public void onLocationChanged(Location location) {
									//On location updates, compare the current location to the desired location set in the place picker
									float fltDistance = location.distanceTo(placePickerFragment.getLocation());
									if (fltDistance >= LOCATION_CHANGE_THRESHOLD) {
										placePickerFragment.setLocation(location);
										//initiate the loading of nearby place data by calling the loadData() on the PlacePickerFragment instance
										placePickerFragment.loadData(true);
									}
								}

								@Override
								public void onStatusChanged(String provider,
										int status, Bundle extras) {

								}

								@Override
								public void onProviderEnabled(String provider) {

								}

								@Override
								public void onProviderDisabled(String provider) {

								}

							};
							locationManager.requestLocationUpdates(strBestProvider, 1, LOCATION_CHANGE_THRESHOLD, locationListener, Looper.getMainLooper());
						}
					}
					if (location == null) {
						//Set the default location if there is no initial location
						String strModel = Build.MODEL;
						if (strModel.equals("sdk") || strModel.equals("google_sdk")	|| strModel.contains("x86")) {
							//This may be the emulator, use the default location
							location = LOCATION_HERZLIYA;
						}
					}
					if (location != null) {
						//Before loading the data, you can configure the PlacePickerFragment instance to specify search criteria like radius, 
						//initial search query and maximum results to return. You can use the LocationManager services to center your search
						placePickerFragment.setLocation(location);
						placePickerFragment.setRadiusInMeters(SEARCH_RADIUS_METERS);
						placePickerFragment.setSearchText(INITIAL_SEARCH_TEXT);
						placePickerFragment.setResultsLimit(SEARCH_RESULT_LIMIT);
						//Start the API call
						placePickerFragment.loadData(true);
					} else {
						//If no location found, show an error
						onError(getResources().getString(R.string.no_location_error), true);
					}
				} catch (Exception ex) {
					onError(ex);
				}
			}
		}
	}

	//making sure you're not listening to location updates when the activity is no longer visible. 
	//You'll do this by overriding the onStop() method to remove the location listener from receiving location updates
	@Override
	protected void onStop() {
		super.onStop();
		if (locationListener != null) {
			LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
			//Remove updates for the location listener
			locationManager.removeUpdates(locationListener);
			locationListener = null;
		}
	}
}
